<?php

namespace app\traits;
use zhtp\Auth as baseAuth;

trait DataScopeTrait
{
    public bool $dataScopeOn = false;

    /**
     * 数据权限范围
     *
     * @param \think\db\Query $query 查询构建器实例
     * @return \think\db\Query
     */
    public function scopeDataScope($query)
    {
        // 是否全局开启数据权限 或 超级管理员
        if (!env('DATA_SCOPE_TRAIT_ON', false) || is_super_admin()) {
            return $query;
        }

        if ($this->dataScopeOn) {
            $request = request();

            if (!empty($request->x_user_data_scope)) {
                $data_scope = $request->x_user_data_scope;

                if ($data_scope[baseAuth::DATA_SCOPE['ALL'][0]] && $data_scope[baseAuth::DATA_SCOPE['ALL'][0]] == true) {
                    return $query;
                } else {
                    // // 方法一：高级查询方式 内部其实也是闭包(tp8.2-orm)；一般via存在时,外面list方法的fields会带上前缀；
                    // $via = $query->getOptions('via');
                    // $prefix_via = $via ? $via . '.' : '';

                    // $where = [];
                    // if ($data_scope[baseAuth::DATA_SCOPE['DEPT'][0]] && !empty($data_scope[baseAuth::DATA_SCOPE['DEPT'][0]])) {
                    //     $where[] = [$prefix_via . 'dept_id', 'in', $data_scope[baseAuth::DATA_SCOPE['DEPT'][0]]];
                    // }
                    // if ($data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]] && $data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]] != 0) {
                    //     $where[] = [$prefix_via . 'dept_id', '=', $data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]]];
                    // }
                    // if ($data_scope[baseAuth::DATA_SCOPE['SELF'][0]] && $data_scope[baseAuth::DATA_SCOPE['SELF'][0]] != 0) {
                    //     $where[] = [$prefix_via . 'admin_id', '=', $data_scope[baseAuth::DATA_SCOPE['SELF'][0]]];
                    // }
                    // $query->whereOr($where);

                    // // 方法二：闭包方式 需要补前缀
                    // $query->where(function ($queryIn) use ($data_scope, $query) {
                    //     $via = $query->getOptions('via');
                    //     $prefix_via = $via ? $via . '.' : '';
                    //     if ($data_scope[baseAuth::DATA_SCOPE['DEPT'][0]] && !empty($data_scope[baseAuth::DATA_SCOPE['DEPT'][0]])) {
                    //         $queryIn->whereOr($prefix_via . 'dept_id', 'in', $data_scope[baseAuth::DATA_SCOPE['DEPT'][0]]);
                    //     }

                    //     if ($data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]] && $data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]] != 0) {
                    //         $queryIn->whereOr($prefix_via . 'dept_id', '=', $data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]]);
                    //     }

                    //     if ($data_scope[baseAuth::DATA_SCOPE['SELF'][0]] && $data_scope[baseAuth::DATA_SCOPE['SELF'][0]] != 0) {
                    //         $queryIn->whereOr($prefix_via . 'admin_id', '=', $data_scope[baseAuth::DATA_SCOPE['SELF'][0]]);
                    //     }
                    // });


                    // // 方法三：优点 会自动带前缀 Role.dept_id； 缺点 下面几个OR没有放在一个括号里,可能会导致SQL语句不正确
                    // if ($data_scope[baseAuth::DATA_SCOPE['DEPT'][0]] && !empty($data_scope[baseAuth::DATA_SCOPE['DEPT'][0]])) {
                    //     $query->whereOr('dept_id', 'in', $data_scope[baseAuth::DATA_SCOPE['DEPT'][0]]);
                    // }

                    // if ($data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]] && $data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]] != 0) {
                    //     $query->whereOr('dept_id', '=', $data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]]);
                    // }

                    // if ($data_scope[baseAuth::DATA_SCOPE['SELF'][0]] && $data_scope[baseAuth::DATA_SCOPE['SELF'][0]] != 0) {
                    //     $query->whereOr('admin_id', '=', $data_scope[baseAuth::DATA_SCOPE['SELF'][0]]);
                    // }

                    // 方法四：优点 会自动带前缀 Role.dept_id； 为避免OR语句导致sql不正确, 全用AND-最小权限,优先级最高
                    if ($data_scope[baseAuth::DATA_SCOPE['NONE'][0]] && $data_scope[baseAuth::DATA_SCOPE['NONE'][0]] != 0) {
                        $query->where('admin_id', '=', $data_scope[baseAuth::DATA_SCOPE['NONE'][0]]);
                        return $query; // 最小权限, 直接返回
                    }

                    if ($data_scope[baseAuth::DATA_SCOPE['SELF'][0]] && $data_scope[baseAuth::DATA_SCOPE['SELF'][0]] != 0) {
                        $query->where('admin_id', '=', $data_scope[baseAuth::DATA_SCOPE['SELF'][0]]);
                        return $query; // 最小权限, 直接返回
                    }

                    if ($data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]] && $data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]] != 0) {
                        $query->where('dept_id', '=', $data_scope[baseAuth::DATA_SCOPE['DEPTSELF'][0]]);
                        return $query;
                    }

                    // 获取自定义权限和本部门及以下权限 同级,否则可能相互冲突
                    $dept_ids = [];
                    if ($data_scope[baseAuth::DATA_SCOPE['DEPT'][0]] && !empty($data_scope[baseAuth::DATA_SCOPE['DEPT'][0]])) {
                        // $query->where('dept_id', 'in', $data_scope[baseAuth::DATA_SCOPE['DEPT'][0]]);
                        $dept_ids = array_merge($dept_ids, $data_scope[baseAuth::DATA_SCOPE['DEPT'][0]]);
                    }

                    if ($data_scope[baseAuth::DATA_SCOPE['CUSTOM'][0]] && !empty($data_scope[baseAuth::DATA_SCOPE['CUSTOM'][0]])) {
                        // $query->where('dept_id', 'in', $data_scope[baseAuth::DATA_SCOPE['CUSTOM'][0]]);
                        $dept_ids = array_merge($dept_ids, $data_scope[baseAuth::DATA_SCOPE['CUSTOM'][0]]);
                    }
                    $deep_ids = array_unique($dept_ids);
                    if (!empty($deep_ids)) {
                        $query->where('dept_id', 'in', $deep_ids);
                        return $query;
                    }


                    // 以上都没有权限,则默认限制下无数据可查,防止越权-(相当于"全部"权限了)
                    return $query->where('dept_id', '=', -99);
                }
            }
        }

        return $query;
    }
}
